<template>
  <div class="excel-converter">
    <div class="container">
      <header class="header">
        <h1 class="main-title">Excel文件转换系统</h1>
        <p class="subtitle">上传Excel文件并查看转换前后的数据对比</p>

        <!-- 🔥 新增：会话状态指示器 -->
        <div class="session-status" :class="sessionStatus">
          <div class="status-dot"></div>
          <span class="status-text">
            {{
              sessionStatus === 'connecting'
                ? '正在连接...'
                : sessionStatus === 'active'
                  ? '会话活跃'
                  : sessionStatus === 'expired'
                    ? '会话已过期'
                    : '连接异常'
            }}
          </span>
          <span v-if="sessionId" class="session-id">{{ sessionId.substring(0, 8) }}</span>
        </div>
      </header>

      <!-- 上传区域 - 转换前显示 -->
      <div v-show="!showResults" class="upload-container">
        <!-- 原始文件上传区域 -->
        <div class="upload-card">
          <h3>上传原始Excel文件</h3>
          <div class="upload-icon">📊</div>
          <div
            class="upload-area"
            @dragover="handleDragOver"
            @dragleave="handleDragLeave"
            @drop="(e) => handleDrop(e, 'source')"
            @click="() => sourceFileInputRef?.click()"
          >
            <p class="upload-text">拖放Excel文件到此处或点击上传</p>
            <input
              ref="sourceFileInputRef"
              type="file"
              accept=".xlsx, .xls"
              style="display: none"
              @change="() => handleFileSelect('source')"
            />
            <button class="browse-button" @click.stop="() => sourceFileInputRef?.click()">
              选择文件
            </button>
          </div>
          <div v-if="sourceFileInfo.name" class="file-info">
            <div class="file-name">{{ sourceFileInfo.name }}</div>
            <div class="file-size">{{ sourceFileInfo.size }}</div>
          </div>
          <div :class="['status-indicator', sourceStatus.class]">
            {{ sourceStatus.text }}
          </div>
        </div>

        <!-- 转换后文件上传区域 -->
        <div class="upload-card">
          <h3>上传模板Excel文件</h3>
          <div class="upload-icon">🔄</div>
          <div
            class="upload-area"
            @dragover="handleDragOver"
            @dragleave="handleDragLeave"
            @drop="(e) => handleDrop(e, 'target')"
            @click="() => targetFileInputRef?.click()"
          >
            <p class="upload-text">拖放模板Excel文件到此处或点击上传</p>
            <input
              ref="targetFileInputRef"
              type="file"
              accept=".xlsx, .xls"
              style="display: none"
              @change="() => handleFileSelect('target')"
            />
            <button class="browse-button" @click.stop="() => targetFileInputRef?.click()">
              选择文件
            </button>
          </div>
          <div v-if="targetFileInfo.name" class="file-info">
            <div class="file-name">{{ targetFileInfo.name }}</div>
            <div class="file-size">{{ targetFileInfo.size }}</div>
          </div>
          <div :class="['status-indicator', targetStatus.class]">
            {{ targetStatus.text }}
          </div>
        </div>
      </div>

      <!-- 转换按钮 - 转换前显示 -->
      <div v-show="!showResults" class="convert-section">
        <button
          class="convert-button"
          :disabled="!canConvert || isConverting || sessionStatus !== 'active'"
          @click="startConversion"
        >
          <span v-if="isConverting" class="loading-spinner"></span>
          <span>{{ convertButtonText }}</span>
        </button>
      </div>

      <!-- AI助手区域 - 文件上传后显示 -->
      <div
        v-show="hasUploadedFiles && !showResults && sessionStatus === 'active'"
        class="chat-container upload-chat"
      >
        <div class="chat-header">
          <div class="chat-title-section">
            <div class="chat-icon">🤖</div>
            <div>
              <h3 class="chat-title">AI数据操作助手</h3>
              <p class="chat-subtitle">文件已上传！试试用自然语言描述数据操作需求</p>
            </div>
          </div>
          <button
            class="chat-toggle"
            @click="toggleUploadChat"
            :class="{ active: isUploadChatExpanded }"
          >
            <span class="toggle-icon">{{ isUploadChatExpanded ? '▼' : '▲' }}</span>
            {{ isUploadChatExpanded ? '收起' : '展开' }}
          </button>
        </div>

        <transition name="chat-collapse">
          <div v-if="isUploadChatExpanded" class="chat-content">
            <!-- 操作提示 -->
            <div class="operation-hints">
              <div class="hint-title">💡 数据操作示例：</div>
              <div class="hint-examples">
                <div
                  class="hint-item"
                  @click="
                    sendQuickOperation(
                      '根据第一个文件的第一个表格的第二、三列内容整理为第二个文件的第一个表格内容',
                    )
                  "
                >
                  <span class="hint-icon">📋</span>
                  根据源文件指定列整理数据
                </div>
                <div
                  class="hint-item"
                  @click="sendQuickOperation('将第一个文件的所有数据按第二个文件的格式重新整理')"
                >
                  <span class="hint-icon">🔄</span>
                  按模板格式转换数据
                </div>
                <div
                  class="hint-item"
                  @click="sendQuickOperation('提取第一个文件第一个表格包含关键词的所有行')"
                >
                  <span class="hint-icon">🔍</span>
                  筛选特定数据行
                </div>
              </div>
            </div>

            <!-- 输入区域 -->
            <div class="chat-input-area">
              <div class="input-wrapper">
                <textarea
                  v-model="uploadChatMessage"
                  @keypress="handleUploadChatKeyPress"
                  @input="adjustUploadChatTextareaHeight"
                  ref="uploadChatInputRef"
                  class="chat-input"
                  placeholder="描述您想要的数据操作，例如：根据第一个文件的前两列生成汇总表..."
                  rows="2"
                  :disabled="isProcessingOperation || sessionStatus !== 'active'"
                ></textarea>
                <button
                  class="send-button"
                  @click="sendUploadChatOperation"
                  :disabled="
                    !uploadChatMessage.trim() || isProcessingOperation || sessionStatus !== 'active'
                  "
                >
                  <span v-if="!isProcessingOperation">执行操作</span>
                  <span v-else class="loading-spinner"></span>
                </button>
              </div>
              <div class="input-hint">按 Enter 执行操作，Shift + Enter 换行</div>
            </div>
          </div>
        </transition>
      </div>

      <!-- 错误消息显示 -->
      <div v-if="errorMessage" class="error-message">
        <div class="error-content">
          <span class="error-icon">❌</span>
          <span>{{ errorMessage }}</span>
          <button class="error-close" @click="clearError">×</button>
        </div>
      </div>

      <!-- 表格显示区域 - 转换后显示 -->
      <div v-show="showResults" class="results-section">
        <!-- 返回按钮 -->
        <div class="back-section">
          <button class="back-button" @click="backToUpload">← 重新开始</button>
          <div class="global-actions">
            <button class="action-btn" @click="collapseAllTables">
              {{ allTablesCollapsed ? '展开全部' : '收起全部' }}
            </button>
            <button
              class="export-button"
              @click="exportResults"
              :disabled="sessionStatus !== 'active'"
            >
              导出结果
            </button>
          </div>
        </div>

        <div class="tables-container">
          <!-- 原始数据表格 -->
          <div class="table-section">
            <div class="table-header">
              <div class="table-title-section">
                <h2 class="table-title">原始Excel数据</h2>
                <div v-if="sourceSheets.length > 0" class="table-info">
                  <span class="sheet-count">{{ sourceSheets.length }} 个工作表</span>
                  <span v-if="currentSourceSheet" class="row-count">
                    {{ currentSourceSheet.rows.length }} 行数据
                  </span>
                </div>
              </div>
              <div class="table-actions">
                <button
                  class="collapse-button"
                  @click="toggleSourceTable"
                  :class="{ active: !sourceTableCollapsed }"
                >
                  <span class="collapse-icon">{{ sourceTableCollapsed ? '▶' : '▼' }}</span>
                  {{ sourceTableCollapsed ? '展开' : '收起' }}
                </button>
                <button class="action-button" @click="refreshSourceData">刷新</button>
              </div>
            </div>

            <div v-if="sourceSheets.length > 0 && !sourceTableCollapsed" class="table-tabs">
              <div
                v-for="(sheet, index) in sourceSheets"
                :key="index"
                :class="['table-tab', { active: activeSourceSheet === index }]"
                @click="activeSourceSheet = index"
              >
                {{ sheet.name }}
                <span class="tab-row-count">({{ sheet.rows.length }})</span>
              </div>
            </div>

            <transition name="table-collapse">
              <div v-if="sourceSheets.length > 0 && !sourceTableCollapsed" class="table-wrapper">
                <table class="data-table">
                  <thead>
                    <tr>
                      <th
                        v-for="(header, index) in currentSourceSheet?.headers"
                        :key="index"
                        :title="header"
                        class="table-cell"
                      >
                        <div class="cell-content">{{ header }}</div>
                      </th>
                    </tr>
                  </thead>
                  <tbody>
                    <tr v-for="(row, rowIndex) in paginatedSourceRows" :key="rowIndex">
                      <td
                        v-for="(cell, cellIndex) in row"
                        :key="cellIndex"
                        :title="String(cell || '')"
                        class="table-cell"
                      >
                        <div :class="getCellClass(cell)">{{ formatCellContent(cell) }}</div>
                      </td>
                    </tr>
                  </tbody>
                </table>
              </div>
            </transition>

            <!-- 原始数据分页组件 -->
            <div
              v-if="sourceSheets.length > 0 && !sourceTableCollapsed && currentSourceSheet"
              class="pagination-container"
            >
              <div class="pagination-info">
                <span class="total-info"> 共 {{ currentSourceSheet.rows.length }} 条数据 </span>
                <div class="page-size-selector">
                  <label>每页显示</label>
                  <select
                    v-model="sourcePageSize"
                    @change="sourceCurrentPage = 1"
                    class="page-size-select"
                  >
                    <option :value="5">5条</option>
                    <option :value="10">10条</option>
                    <option :value="15">15条</option>
                    <option :value="20">20条</option>
                    <option :value="25">25条</option>
                  </select>
                </div>
              </div>

              <div class="pagination-controls">
                <button
                  :disabled="sourceCurrentPage === 1"
                  @click="sourceCurrentPage = 1"
                  class="pagination-btn"
                >
                  首页
                </button>
                <button
                  :disabled="sourceCurrentPage === 1"
                  @click="sourceCurrentPage--"
                  class="pagination-btn"
                >
                  上一页
                </button>

                <div class="pagination-pages">
                  <button
                    v-for="page in getSourcePageNumbers"
                    :key="page"
                    @click="sourceCurrentPage = page"
                    :class="['pagination-btn', 'page-btn', { active: sourceCurrentPage === page }]"
                  >
                    {{ page }}
                  </button>
                </div>

                <button
                  :disabled="sourceCurrentPage === sourceTotalPages"
                  @click="sourceCurrentPage++"
                  class="pagination-btn"
                >
                  下一页
                </button>
                <button
                  :disabled="sourceCurrentPage === sourceTotalPages"
                  @click="sourceCurrentPage = sourceTotalPages"
                  class="pagination-btn"
                >
                  末页
                </button>
              </div>

              <div class="pagination-jump">
                <span>跳转到</span>
                <input
                  v-model.number="sourceJumpPage"
                  @keyup.enter="jumpToSourcePage"
                  type="number"
                  :min="1"
                  :max="sourceTotalPages"
                  class="page-jump-input"
                />
                <span>页</span>
                <button @click="jumpToSourcePage" class="jump-btn">确定</button>
              </div>
            </div>

            <div v-if="sourceSheets.length === 0" class="empty-state">
              <div class="empty-icon">📊</div>
              <p>暂无原始数据</p>
            </div>

            <!-- 折叠时的摘要信息 -->
            <div v-if="sourceSheets.length > 0 && sourceTableCollapsed" class="table-summary">
              <div class="summary-card">
                <div class="summary-icon">📊</div>
                <div class="summary-content">
                  <div class="summary-title">数据已折叠</div>
                  <div class="summary-details">
                    共 {{ sourceSheets.length }} 个工作表， 当前表格 "{{
                      currentSourceSheet?.name
                    }}" 包含 {{ currentSourceSheet?.rows.length }} 行数据
                  </div>
                </div>
              </div>
            </div>
          </div>

          <!-- 转换后数据表格 -->
          <div class="table-section">
            <div class="table-header">
              <div class="table-title-section">
                <h2 class="table-title">{{ operationResultTitle }}</h2>
                <div v-if="convertedSheets.length > 0" class="table-info">
                  <span class="sheet-count">{{ convertedSheets.length }} 个工作表</span>
                  <span v-if="currentConvertedSheet" class="row-count">
                    {{ currentConvertedSheet.rows.length }} 行数据
                  </span>
                </div>
              </div>
              <div class="table-actions">
                <button
                  class="collapse-button"
                  @click="toggleConvertedTable"
                  :class="{ active: !convertedTableCollapsed }"
                >
                  <span class="collapse-icon">{{ convertedTableCollapsed ? '▶' : '▼' }}</span>
                  {{ convertedTableCollapsed ? '展开' : '收起' }}
                </button>
                <button class="action-button" @click="refreshConvertedData">刷新</button>
              </div>
            </div>

            <div v-if="convertedSheets.length > 0 && !convertedTableCollapsed" class="table-tabs">
              <div
                v-for="(sheet, index) in convertedSheets"
                :key="index"
                :class="['table-tab', { active: activeConvertedSheet === index }]"
                @click="activeConvertedSheet = index"
              >
                {{ sheet.name }}
                <span class="tab-row-count">({{ sheet.rows.length }})</span>
              </div>
            </div>

            <transition name="table-collapse">
              <div
                v-if="convertedSheets.length > 0 && !convertedTableCollapsed"
                class="table-wrapper"
              >
                <table class="data-table">
                  <thead>
                    <tr>
                      <th
                        v-for="(header, index) in currentConvertedSheet?.headers"
                        :key="index"
                        :title="header"
                        class="table-cell"
                      >
                        <div class="cell-content">{{ header }}</div>
                      </th>
                    </tr>
                  </thead>
                  <tbody>
                    <tr v-for="(row, rowIndex) in paginatedConvertedRows" :key="rowIndex">
                      <td
                        v-for="(cell, cellIndex) in row"
                        :key="cellIndex"
                        :title="String(cell || '')"
                        class="table-cell"
                      >
                        <div :class="getCellClass(cell)">{{ formatCellContent(cell) }}</div>
                      </td>
                    </tr>
                  </tbody>
                </table>
              </div>
            </transition>

            <!-- 转换后数据分页组件 -->
            <div
              v-if="convertedSheets.length > 0 && !convertedTableCollapsed && currentConvertedSheet"
              class="pagination-container"
            >
              <div class="pagination-info">
                <span class="total-info"> 共 {{ currentConvertedSheet.rows.length }} 条数据 </span>
                <div class="page-size-selector">
                  <label>每页显示</label>
                  <select
                    v-model="convertedPageSize"
                    @change="convertedCurrentPage = 1"
                    class="page-size-select"
                  >
                    <option :value="5">5条</option>
                    <option :value="10">10条</option>
                    <option :value="15">15条</option>
                    <option :value="20">20条</option>
                    <option :value="25">25条</option>
                  </select>
                </div>
              </div>

              <div class="pagination-controls">
                <button
                  :disabled="convertedCurrentPage === 1"
                  @click="convertedCurrentPage = 1"
                  class="pagination-btn"
                >
                  首页
                </button>
                <button
                  :disabled="convertedCurrentPage === 1"
                  @click="convertedCurrentPage--"
                  class="pagination-btn"
                >
                  上一页
                </button>

                <div class="pagination-pages">
                  <button
                    v-for="page in getConvertedPageNumbers"
                    :key="page"
                    @click="convertedCurrentPage = page"
                    :class="[
                      'pagination-btn',
                      'page-btn',
                      { active: convertedCurrentPage === page },
                    ]"
                  >
                    {{ page }}
                  </button>
                </div>

                <button
                  :disabled="convertedCurrentPage === convertedTotalPages"
                  @click="convertedCurrentPage++"
                  class="pagination-btn"
                >
                  下一页
                </button>
                <button
                  :disabled="convertedCurrentPage === convertedTotalPages"
                  @click="convertedCurrentPage = convertedTotalPages"
                  class="pagination-btn"
                >
                  末页
                </button>
              </div>

              <div class="pagination-jump">
                <span>跳转到</span>
                <input
                  v-model.number="convertedJumpPage"
                  @keyup.enter="jumpToConvertedPage"
                  type="number"
                  :min="1"
                  :max="convertedTotalPages"
                  class="page-jump-input"
                />
                <span>页</span>
                <button @click="jumpToConvertedPage" class="jump-btn">确定</button>
              </div>
            </div>

            <div v-if="convertedSheets.length === 0" class="empty-state">
              <div class="empty-icon">🔄</div>
              <p>暂无转换后数据</p>
            </div>

            <!-- 折叠时的摘要信息 -->
            <div v-if="convertedSheets.length > 0 && convertedTableCollapsed" class="table-summary">
              <div class="summary-card">
                <div class="summary-icon">🔄</div>
                <div class="summary-content">
                  <div class="summary-title">数据已折叠</div>
                  <div class="summary-details">
                    共 {{ convertedSheets.length }} 个工作表， 当前表格 "{{
                      currentConvertedSheet?.name
                    }}" 包含 {{ currentConvertedSheet?.rows.length }} 行数据
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>

        <!-- AI助手对话框 -->
        <div class="chat-container" v-if="sessionStatus === 'active'">
          <div class="chat-header">
            <div class="chat-title-section">
              <div class="chat-icon">🤖</div>
              <div>
                <h3 class="chat-title">AI转换助手</h3>
                <p class="chat-subtitle">继续操作数据或咨询问题</p>
              </div>
            </div>
            <button class="chat-toggle" @click="toggleChat" :class="{ active: isChatExpanded }">
              <span class="toggle-icon">{{ isChatExpanded ? '▼' : '▲' }}</span>
              {{ isChatExpanded ? '收起' : '展开' }}
            </button>
          </div>

          <transition name="chat-collapse">
            <div v-if="isChatExpanded" class="chat-content">
              <!-- 消息列表 -->
              <div class="chat-messages" ref="chatMessagesRef">
                <div
                  v-for="(message, index) in chatMessages"
                  :key="index"
                  :class="['message', message.type]"
                >
                  <div class="message-avatar">
                    <span v-if="message.type === 'user'">👤</span>
                    <span v-else>🤖</span>
                  </div>
                  <div class="message-content">
                    <div class="message-text" v-html="formatMessageText(message.text)"></div>
                    <div class="message-time">{{ message.time }}</div>
                  </div>
                </div>

                <!-- 正在输入指示器 -->
                <div v-if="isAITyping" class="message assistant typing">
                  <div class="message-avatar">🤖</div>
                  <div class="message-content">
                    <div class="typing-indicator">
                      <span></span>
                      <span></span>
                      <span></span>
                    </div>
                  </div>
                </div>
              </div>

              <!-- 快捷问题 -->
              <div v-if="chatMessages.length === 0" class="quick-questions">
                <div class="quick-title">💡 快捷操作：</div>
                <div class="quick-buttons">
                  <button
                    v-for="question in quickQuestions"
                    :key="question"
                    class="quick-button"
                    @click="sendQuickQuestion(question)"
                  >
                    {{ question }}
                  </button>
                </div>
              </div>

              <!-- 输入区域 -->
              <div class="chat-input-area">
                <div class="input-wrapper">
                  <textarea
                    v-model="currentMessage"
                    @keypress="handleKeyPress"
                    @input="adjustTextareaHeight"
                    ref="chatInputRef"
                    class="chat-input"
                    placeholder="继续操作数据或询问问题..."
                    rows="1"
                    :disabled="isAITyping || sessionStatus !== 'active'"
                  ></textarea>
                  <button
                    class="send-button"
                    @click="sendMessage"
                    :disabled="!currentMessage.trim() || isAITyping || sessionStatus !== 'active'"
                  >
                    <span v-if="!isAITyping">发送</span>
                    <span v-else class="loading-spinner"></span>
                  </button>
                </div>
                <div class="input-hint">按 Enter 发送，Shift + Enter 换行</div>
              </div>
            </div>
          </transition>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, nextTick, watch, onMounted } from 'vue'

// 类型定义
interface ExcelSheet {
  name: string
  headers: string[]
  rows: (string | number)[][]
}

interface FileInfo {
  name: string
  size: string
}

interface Status {
  text: string
  class: string
}

interface ChatMessage {
  type: 'user' | 'assistant'
  text: string
  time: string
}

type FileType = 'source' | 'target'

// 🔥 新增：会话管理
const sessionId = ref<string>('')
const sessionStatus = ref<'connecting' | 'active' | 'expired' | 'error'>('connecting')

// API配置
const API_BASE_URL = 'http://127.0.0.1:8802/api'

// 响应式数据
const sourceFileInputRef = ref<HTMLInputElement>()
const targetFileInputRef = ref<HTMLInputElement>()

const sourceFile = ref<File | null>(null)
const targetFile = ref<File | null>(null)

const sourceFileInfo = ref<FileInfo>({
  name: '',
  size: '',
})

const targetFileInfo = ref<FileInfo>({
  name: '',
  size: '',
})

const sourceStatus = ref<Status>({
  text: '等待上传',
  class: 'status-waiting',
})

const targetStatus = ref<Status>({
  text: '等待上传',
  class: 'status-waiting',
})

const sourceSheets = ref<ExcelSheet[]>([])
const targetSheets = ref<ExcelSheet[]>([])
const convertedSheets = ref<ExcelSheet[]>([])

const activeSourceSheet = ref(0)
const activeTargetSheet = ref(0)
const activeConvertedSheet = ref(0)

const isConverting = ref(false)
const showResults = ref(false)
const errorMessage = ref('')

// 表格折叠状态控制
const sourceTableCollapsed = ref(false)
const convertedTableCollapsed = ref(false)

// 分页相关数据
const sourcePageSize = ref(10)
const sourceCurrentPage = ref(1)
const sourceJumpPage = ref(1)

const convertedPageSize = ref(10)
const convertedCurrentPage = ref(1)
const convertedJumpPage = ref(1)

// 对话框相关数据
const isChatExpanded = ref(false)
const currentMessage = ref('')
const isAITyping = ref(false)
const chatMessages = ref<ChatMessage[]>([])

// 🔥 新增：上传后的对话框状态
const isUploadChatExpanded = ref(false)
const uploadChatMessage = ref('')
const isProcessingOperation = ref(false)

// 🔥 新增：操作相关状态
const lastOperationType = ref('')
const operationResultTitle = computed(() => {
  if (lastOperationType.value) {
    return `AI操作结果 (${lastOperationType.value})`
  }
  return '转换后Excel数据'
})

const chatMessagesRef = ref<HTMLElement>()
const chatInputRef = ref<HTMLTextAreaElement>()
const uploadChatInputRef = ref<HTMLTextAreaElement>()

// 🔥 修改后的快捷问题
const quickQuestions = [
  '根据第一个文件的前两列生成汇总表',
  '将源文件的所有数据合并到目标格式',
  '提取第一个表格包含关键词的数据行',
  '按照模板格式重新整理数据',
  '如何进行更复杂的数据操作？',
]

// 计算属性
const currentSourceSheet = computed(() => sourceSheets.value[activeSourceSheet.value] || null)

const currentTargetSheet = computed(() => targetSheets.value[activeTargetSheet.value] || null)

const currentConvertedSheet = computed(
  () => convertedSheets.value[activeConvertedSheet.value] || null,
)

const convertButtonText = computed(() => {
  if (isConverting.value) return '转换中...'
  if (sessionStatus.value !== 'active') return '会话连接中...'
  return '开始转换'
})

const canConvert = computed(() => {
  return (
    sourceFile.value && targetFile.value && !isConverting.value && sessionStatus.value === 'active'
  )
})

const allTablesCollapsed = computed(() => {
  return sourceTableCollapsed.value && convertedTableCollapsed.value
})

// 🔥 新增：是否已上传文件
const hasUploadedFiles = computed(() => {
  return sourceSheets.value.length > 0 && targetSheets.value.length > 0
})

// 分页计算属性
const sourceTotalPages = computed(() => {
  if (!currentSourceSheet.value) return 0
  return Math.ceil(currentSourceSheet.value.rows.length / sourcePageSize.value)
})

const convertedTotalPages = computed(() => {
  if (!currentConvertedSheet.value) return 0
  return Math.ceil(currentConvertedSheet.value.rows.length / convertedPageSize.value)
})

const paginatedSourceRows = computed(() => {
  if (!currentSourceSheet.value) return []
  const start = (sourceCurrentPage.value - 1) * sourcePageSize.value
  const end = start + sourcePageSize.value
  return currentSourceSheet.value.rows.slice(start, end)
})

const paginatedConvertedRows = computed(() => {
  if (!currentConvertedSheet.value) return []
  const start = (convertedCurrentPage.value - 1) * convertedPageSize.value
  const end = start + convertedPageSize.value
  return currentConvertedSheet.value.rows.slice(start, end)
})

const getSourcePageNumbers = computed(() => {
  return generatePageNumbers(sourceCurrentPage.value, sourceTotalPages.value)
})

const getConvertedPageNumbers = computed(() => {
  return generatePageNumbers(convertedCurrentPage.value, convertedTotalPages.value)
})

// 🔥 新增：会话管理方法
const createSession = async (): Promise<boolean> => {
  try {
    const response = await fetch(`${API_BASE_URL}/create-session`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
    })

    if (!response.ok) {
      throw new Error('创建会话失败')
    }

    const data = await response.json()
    sessionId.value = data.session_id
    sessionStatus.value = 'active'

    console.log('✅ 会话创建成功:', sessionId.value)
    return true
  } catch (error) {
    console.error('❌ 创建会话失败:', error)
    sessionStatus.value = 'error'
    showError('无法创建会话，请刷新页面重试')
    return false
  }
}

// 🔥 新增：检查会话状态
const checkSessionStatus = async (): Promise<boolean> => {
  if (!sessionId.value) return false

  try {
    const response = await fetch(
      `${API_BASE_URL}/get-session-context?session_id=${sessionId.value}`,
    )

    if (response.ok) {
      sessionStatus.value = 'active'
      return true
    } else {
      sessionStatus.value = 'expired'
      return false
    }
  } catch (error) {
    sessionStatus.value = 'error'
    return false
  }
}

// 🔥 新增：处理会话过期
const handleSessionExpired = async () => {
  sessionStatus.value = 'expired'
  showError('会话已过期，正在重新创建...')

  // 重新创建会话
  const success = await createSession()
  if (success) {
    showError('会话已重新创建，请重新上传文件')
    // 重置状态
    backToUpload()
  }
}

// 表格内容处理工具方法
const isNumeric = (value: any): boolean => {
  return !isNaN(parseFloat(value)) && isFinite(value)
}

const formatCellContent = (cell: any): string => {
  if (cell === null || cell === undefined) return ''
  const cellStr = String(cell)
  if (cellStr.length > 30) {
    return cellStr.substring(0, 27) + '...'
  }
  return cellStr
}

const getCellClass = (cell: any): string => {
  const classes = ['cell-content']
  if (isNumeric(cell)) {
    classes.push('number')
  }
  if (String(cell).length > 20) {
    classes.push('long-text')
  }
  return classes.join(' ')
}

// 🔥 新增：格式化消息文本（支持HTML）
const formatMessageText = (text: string): string => {
  return text
    .replace(/\n/g, '<br>')
    .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
    .replace(/\*(.*?)\*/g, '<em>$1</em>')
    .replace(/(✅|❌|💡|📊|🔄|🔍|📋)/g, '<span class="emoji">$1</span>')
}

// 分页工具方法
const generatePageNumbers = (currentPage: number, totalPages: number) => {
  const pages = []
  const maxVisiblePages = 5

  if (totalPages <= maxVisiblePages) {
    for (let i = 1; i <= totalPages; i++) {
      pages.push(i)
    }
  } else {
    const start = Math.max(1, currentPage - Math.floor(maxVisiblePages / 2))
    const end = Math.min(totalPages, start + maxVisiblePages - 1)
    const adjustedStart = Math.max(1, end - maxVisiblePages + 1)

    for (let i = adjustedStart; i <= end; i++) {
      pages.push(i)
    }
  }

  return pages
}

const jumpToSourcePage = () => {
  if (sourceJumpPage.value >= 1 && sourceJumpPage.value <= sourceTotalPages.value) {
    sourceCurrentPage.value = sourceJumpPage.value
  }
  sourceJumpPage.value = sourceCurrentPage.value
}

const jumpToConvertedPage = () => {
  if (convertedJumpPage.value >= 1 && convertedJumpPage.value <= convertedTotalPages.value) {
    convertedCurrentPage.value = convertedJumpPage.value
  }
  convertedJumpPage.value = convertedCurrentPage.value
}

// 工具方法
const formatFileSize = (bytes: number): string => {
  if (bytes === 0) return '0 B'

  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))

  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

const showError = (message: string) => {
  errorMessage.value = message
  setTimeout(() => {
    errorMessage.value = ''
  }, 5000)
}

const clearError = () => {
  errorMessage.value = ''
}

// 表格折叠控制方法
const toggleSourceTable = () => {
  sourceTableCollapsed.value = !sourceTableCollapsed.value
}

const toggleConvertedTable = () => {
  convertedTableCollapsed.value = !convertedTableCollapsed.value
}

const collapseAllTables = () => {
  if (allTablesCollapsed.value) {
    // 如果全部折叠，则展开全部
    sourceTableCollapsed.value = false
    convertedTableCollapsed.value = false
  } else {
    // 否则折叠全部
    sourceTableCollapsed.value = true
    convertedTableCollapsed.value = true
  }
}

// 🔥 新增：上传后对话框方法
const toggleUploadChat = () => {
  isUploadChatExpanded.value = !isUploadChatExpanded.value
  if (isUploadChatExpanded.value) {
    nextTick(() => {
      uploadChatInputRef.value?.focus()
    })
  }
}

const sendQuickOperation = (operation: string) => {
  uploadChatMessage.value = operation
  sendUploadChatOperation()
}

const handleUploadChatKeyPress = (e: KeyboardEvent) => {
  if (e.key === 'Enter' && !e.shiftKey) {
    e.preventDefault()
    sendUploadChatOperation()
  }
}

const adjustUploadChatTextareaHeight = () => {
  const textarea = uploadChatInputRef.value
  if (textarea) {
    textarea.style.height = 'auto'
    textarea.style.height = Math.min(textarea.scrollHeight, 120) + 'px'
  }
}

// 🔥 修改：执行上传后的数据操作
const sendUploadChatOperation = async () => {
  if (!uploadChatMessage.value.trim() || isProcessingOperation.value || !sessionId.value) return

  const instruction = uploadChatMessage.value.trim()
  uploadChatMessage.value = ''
  isProcessingOperation.value = true

  // 检查会话状态
  const sessionValid = await checkSessionStatus()
  if (!sessionValid) {
    await handleSessionExpired()
    isProcessingOperation.value = false
    return
  }

  try {
    const response = await fetch(`${API_BASE_URL}/data-operation`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        session_id: sessionId.value,
        instruction: instruction,
      }),
    })

    if (!response.ok) {
      if (response.status === 400) {
        await handleSessionExpired()
        return
      }
      throw new Error('数据操作执行失败')
    }

    const data = await response.json()

    if (data.success && data.operationResult) {
      // 更新转换后的数据
      convertedSheets.value = data.operationResult
      lastOperationType.value = data.operation || '数据操作'

      // 切换到结果显示
      showResults.value = true
      convertedTableCollapsed.value = false
      sourceTableCollapsed.value = false

      // 添加成功消息到聊天记录
      chatMessages.value.push({
        type: 'assistant',
        text: `✅ ${data.message || '操作完成'}\n\n📊 已生成 ${data.operationResult.length} 个工作表，您可以查看结果并继续操作。`,
        time: new Date().toLocaleTimeString('zh-CN', {
          hour: '2-digit',
          minute: '2-digit',
        }),
      })
    } else {
      throw new Error(data.error || '数据操作失败')
    }
  } catch (error) {
    showError(`操作失败：${error instanceof Error ? error.message : '未知错误'}`)
  } finally {
    isProcessingOperation.value = false
    nextTick(() => {
      adjustUploadChatTextareaHeight()
    })
  }
}

// 对话框方法
const toggleChat = () => {
  isChatExpanded.value = !isChatExpanded.value
  if (isChatExpanded.value) {
    // 展开时聚焦输入框
    nextTick(() => {
      chatInputRef.value?.focus()
    })
  }
}

const sendQuickQuestion = (question: string) => {
  currentMessage.value = question
  sendMessage()
}

// 🔥 修改后的发送消息方法
const sendMessage = async () => {
  if (!currentMessage.value.trim() || isAITyping.value || !sessionId.value) return

  const userMessage: ChatMessage = {
    type: 'user',
    text: currentMessage.value.trim(),
    time: new Date().toLocaleTimeString('zh-CN', {
      hour: '2-digit',
      minute: '2-digit',
    }),
  }

  chatMessages.value.push(userMessage)
  const messageToSend = currentMessage.value.trim()
  currentMessage.value = ''

  nextTick(() => {
    scrollChatToBottom()
  })

  isAITyping.value = true

  try {
    // 🔥 检查是否为数据操作指令
    if (isDataOperationCommand(messageToSend)) {
      await handleDataOperation(messageToSend)
    } else {
      // 普通聊天
      await handleChatMessage(messageToSend)
    }
  } catch (error) {
    const errorMessage: ChatMessage = {
      type: 'assistant',
      text: '抱歉，我遇到了一些技术问题。请稍后再试。',
      time: new Date().toLocaleTimeString('zh-CN', {
        hour: '2-digit',
        minute: '2-digit',
      }),
    }
    chatMessages.value.push(errorMessage)
    console.error('AI operation error:', error)
  } finally {
    isAITyping.value = false
    nextTick(() => {
      scrollChatToBottom()
      adjustTextareaHeight()
    })
  }
}

// 🔥 新增：判断是否为数据操作指令
const isDataOperationCommand = (message: string): boolean => {
  const operationKeywords = [
    '整理',
    '转换',
    '提取',
    '合并',
    '筛选',
    '排序',
    '根据.*列',
    '第.*文件',
    '第.*表格',
    '生成',
    '计算',
    '统计',
    '汇总',
    '分组',
    '按照.*格式',
    '重新整理',
    '导出',
    '处理',
    '清洗',
  ]

  return operationKeywords.some((keyword) => new RegExp(keyword, 'i').test(message))
}

// 🔥 修改：处理数据操作指令
const handleDataOperation = async (instruction: string) => {
  if (!sessionId.value) return

  // 检查会话状态
  const sessionValid = await checkSessionStatus()
  if (!sessionValid) {
    await handleSessionExpired()
    return
  }

  try {
    const response = await fetch(`${API_BASE_URL}/data-operation`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        session_id: sessionId.value,
        instruction: instruction,
      }),
    })

    if (!response.ok) {
      if (response.status === 400) {
        await handleSessionExpired()
        return
      }
      throw new Error('数据操作执行失败')
    }

    const data = await response.json()

    if (data.success && data.operationResult) {
      // 更新转换后的数据
      convertedSheets.value = data.operationResult
      lastOperationType.value = data.operation || '数据操作'

      // 显示AI回复
      const aiMessage: ChatMessage = {
        type: 'assistant',
        text: `✅ 操作完成！${data.message || '已根据您的指令重新整理数据。'}\n\n📊 **处理结果**：\n- 生成了 ${data.operationResult.length} 个工作表\n- 您可以继续进行其他操作或导出结果`,
        time: new Date().toLocaleTimeString('zh-CN', {
          hour: '2-digit',
          minute: '2-digit',
        }),
      }
      chatMessages.value.push(aiMessage)

      // 自动展开转换后的表格
      convertedTableCollapsed.value = false
    } else {
      throw new Error(data.error || '数据操作失败')
    }
  } catch (error) {
    const errorMessage: ChatMessage = {
      type: 'assistant',
      text: `❌ 数据操作失败：${error instanceof Error ? error.message : '未知错误'}\n\n💡 **请检查**：\n1. 数据操作指令是否清晰\n2. 会话是否有效\n3. 是否已上传相关文件`,
      time: new Date().toLocaleTimeString('zh-CN', {
        hour: '2-digit',
        minute: '2-digit',
      }),
    }
    chatMessages.value.push(errorMessage)
  }
}

// 🔥 修改：处理普通聊天消息
const handleChatMessage = async (message: string) => {
  if (!sessionId.value) {
    const errorMessage: ChatMessage = {
      type: 'assistant',
      text: '会话已失效，请刷新页面重新开始。',
      time: new Date().toLocaleTimeString('zh-CN', {
        hour: '2-digit',
        minute: '2-digit',
      }),
    }
    chatMessages.value.push(errorMessage)
    return
  }

  // 检查会话状态
  const sessionValid = await checkSessionStatus()
  if (!sessionValid) {
    await handleSessionExpired()
    return
  }

  const response = await fetch(`${API_BASE_URL}/chat`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      session_id: sessionId.value,
      message: message,
    }),
  })

  if (!response.ok) {
    if (response.status === 400) {
      await handleSessionExpired()
      return
    }
    throw new Error('AI响应失败')
  }

  const data = await response.json()
  const aiMessage: ChatMessage = {
    type: 'assistant',
    text: data.response || '抱歉，我现在无法回答这个问题。',
    time: new Date().toLocaleTimeString('zh-CN', {
      hour: '2-digit',
      minute: '2-digit',
    }),
  }
  chatMessages.value.push(aiMessage)
}

const handleKeyPress = (e: KeyboardEvent) => {
  if (e.key === 'Enter' && !e.shiftKey) {
    e.preventDefault()
    sendMessage()
  }
}

const adjustTextareaHeight = () => {
  const textarea = chatInputRef.value
  if (textarea) {
    textarea.style.height = 'auto'
    textarea.style.height = Math.min(textarea.scrollHeight, 120) + 'px'
  }
}

const scrollChatToBottom = () => {
  const messagesContainer = chatMessagesRef.value
  if (messagesContainer) {
    messagesContainer.scrollTop = messagesContainer.scrollHeight
  }
}

// 🔥 修改：文件上传方法
const uploadFiles = async (): Promise<{
  sourceData: ExcelSheet[]
  targetData: ExcelSheet[]
} | null> => {
  if (!sourceFile.value || !targetFile.value || !sessionId.value) return null

  // 检查会话状态
  const sessionValid = await checkSessionStatus()
  if (!sessionValid) {
    await handleSessionExpired()
    return null
  }

  const formData = new FormData()
  formData.append('sourceFile', sourceFile.value)
  formData.append('targetFile', targetFile.value)
  formData.append('session_id', sessionId.value)

  try {
    const response = await fetch(`${API_BASE_URL}/upload`, {
      method: 'POST',
      body: formData,
    })

    if (!response.ok) {
      if (response.status === 400) {
        // 可能是会话过期
        await handleSessionExpired()
        return null
      }
      const errorData = await response.json()
      throw new Error(errorData.error || '上传失败')
    }

    const data = await response.json()
    return {
      sourceData: data.sourceData,
      targetData: data.targetData,
    }
  } catch (error) {
    console.error('文件上传失败:', error)
    showError(`文件上传失败: ${error instanceof Error ? error.message : '未知错误'}`)
    return null
  }
}

// 🔥 修改：数据转换方法
const convertData = async (): Promise<ExcelSheet[] | null> => {
  if (!sessionId.value) return null

  // 检查会话状态
  const sessionValid = await checkSessionStatus()
  if (!sessionValid) {
    await handleSessionExpired()
    return null
  }

  try {
    const response = await fetch(`${API_BASE_URL}/convert`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        session_id: sessionId.value,
      }),
    })

    if (!response.ok) {
      if (response.status === 400) {
        await handleSessionExpired()
        return null
      }
      const errorData = await response.json()
      throw new Error(errorData.error || '转换失败')
    }

    const data = await response.json()
    return data.convertedData
  } catch (error) {
    console.error('数据转换失败:', error)
    showError(`数据转换失败: ${error instanceof Error ? error.message : '未知错误'}`)
    return null
  }
}

// 🔥 修改：导出方法
const exportData = async (): Promise<void> => {
  if (!sessionId.value) return

  // 检查会话状态
  const sessionValid = await checkSessionStatus()
  if (!sessionValid) {
    await handleSessionExpired()
    return
  }

  try {
    const response = await fetch(`${API_BASE_URL}/export`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        session_id: sessionId.value,
      }),
    })

    if (!response.ok) {
      const errorData = await response.json()
      throw new Error(errorData.error || '导出失败')
    }

    const blob = await response.blob()
    const url = window.URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.style.display = 'none'
    a.href = url
    a.download = '转换结果.xlsx'
    document.body.appendChild(a)
    a.click()
    window.URL.revokeObjectURL(url)
    document.body.removeChild(a)
  } catch (error) {
    console.error('导出失败:', error)
    showError(`导出失败: ${error instanceof Error ? error.message : '未知错误'}`)
  }
}

// 事件处理方法
const handleDragOver = (e: DragEvent) => {
  e.preventDefault()
  const target = e.currentTarget as HTMLElement
  target.style.borderColor = '#3b82f6'
  target.style.backgroundColor = 'rgba(59, 130, 246, 0.05)'
}

const handleDragLeave = (e: DragEvent) => {
  const target = e.currentTarget as HTMLElement
  target.style.borderColor = 'rgba(59, 130, 246, 0.3)'
  target.style.backgroundColor = ''
}

const handleDrop = (e: DragEvent, type: FileType) => {
  e.preventDefault()
  const target = e.currentTarget as HTMLElement
  target.style.borderColor = 'rgba(59, 130, 246, 0.3)'
  target.style.backgroundColor = ''

  if (e.dataTransfer?.files.length) {
    const file = e.dataTransfer.files[0]
    processFile(file, type)
  }
}

const handleFileSelect = (type: FileType) => {
  const fileInput = type === 'source' ? sourceFileInputRef.value : targetFileInputRef.value
  const file = fileInput?.files?.[0]

  if (file) {
    processFile(file, type)
  }
}

const processFile = async (file: File, type: FileType) => {
  if (type === 'source') {
    sourceFile.value = file
    sourceFileInfo.value = {
      name: file.name,
      size: formatFileSize(file.size),
    }
    sourceStatus.value = {
      text: '文件已选择',
      class: 'status-ready',
    }
  } else {
    targetFile.value = file
    targetFileInfo.value = {
      name: file.name,
      size: formatFileSize(file.size),
    }
    targetStatus.value = {
      text: '文件已选择',
      class: 'status-ready',
    }
  }

  // 🔥 如果两个文件都已上传，自动解析并显示操作区域
  if (
    sourceFile.value &&
    targetFile.value &&
    sourceSheets.value.length === 0 &&
    sessionStatus.value === 'active'
  ) {
    await autoParseFiles()
  }
}

// 🔥 新增：自动解析文件
const autoParseFiles = async () => {
  try {
    sourceStatus.value = { text: '解析中...', class: 'status-processing' }
    targetStatus.value = { text: '解析中...', class: 'status-processing' }

    const uploadResult = await uploadFiles()
    if (uploadResult) {
      sourceSheets.value = uploadResult.sourceData
      targetSheets.value = uploadResult.targetData

      sourceStatus.value = { text: '解析完成', class: 'status-ready' }
      targetStatus.value = { text: '解析完成', class: 'status-ready' }

      // 自动展开操作区域
      isUploadChatExpanded.value = true
    }
  } catch (error) {
    sourceStatus.value = { text: '解析失败', class: 'status-waiting' }
    targetStatus.value = { text: '解析失败', class: 'status-waiting' }
  }
}

// 🔥 修改：传统转换方法
const startConversion = async () => {
  if (!canConvert.value || !sessionId.value) return

  isConverting.value = true
  clearError()

  // 检查会话状态
  const sessionValid = await checkSessionStatus()
  if (!sessionValid) {
    await handleSessionExpired()
    isConverting.value = false
    return
  }

  sourceStatus.value = {
    text: '上传中...',
    class: 'status-processing',
  }
  targetStatus.value = {
    text: '上传中...',
    class: 'status-processing',
  }

  try {
    // 1. 上传文件并解析（如果还没解析的话）
    let uploadResult = null
    if (sourceSheets.value.length === 0) {
      uploadResult = await uploadFiles()
      if (!uploadResult) {
        throw new Error('文件上传失败')
      }
      sourceSheets.value = uploadResult.sourceData
      targetSheets.value = uploadResult.targetData
    }

    sourceStatus.value = {
      text: '上传完成',
      class: 'status-ready',
    }
    targetStatus.value = {
      text: '模板已加载',
      class: 'status-ready',
    }

    // 2. 调用AI进行数据转换
    sourceStatus.value = {
      text: '转换中...',
      class: 'status-processing',
    }

    const convertedData = await convertData()
    if (!convertedData) {
      throw new Error('数据转换失败')
    }

    convertedSheets.value = convertedData
    lastOperationType.value = '传统转换'

    sourceStatus.value = {
      text: '转换完成',
      class: 'status-ready',
    }
    targetStatus.value = {
      text: '转换完成',
      class: 'status-ready',
    }

    // 3. 切换到结果页面
    showResults.value = true
    sourceTableCollapsed.value = false
    convertedTableCollapsed.value = false
  } catch (error) {
    console.error('转换过程失败:', error)
    sourceStatus.value = {
      text: '转换失败',
      class: 'status-waiting',
    }
    targetStatus.value = {
      text: '转换失败',
      class: 'status-waiting',
    }
  } finally {
    isConverting.value = false
  }
}

// 其他方法
const backToUpload = async () => {
  showResults.value = false

  // 重置本地状态
  sourceFile.value = null
  targetFile.value = null
  sourceSheets.value = []
  targetSheets.value = []
  convertedSheets.value = []
  sourceStatus.value = { text: '等待上传', class: 'status-waiting' }
  targetStatus.value = { text: '等待上传', class: 'status-waiting' }
  sourceFileInfo.value = { name: '', size: '' }
  targetFileInfo.value = { name: '', size: '' }

  // 重置其他状态
  sourceTableCollapsed.value = false
  convertedTableCollapsed.value = false
  sourcePageSize.value = 10
  sourceCurrentPage.value = 1
  sourceJumpPage.value = 1
  convertedPageSize.value = 10
  convertedCurrentPage.value = 1
  convertedJumpPage.value = 1
  isChatExpanded.value = false
  isUploadChatExpanded.value = false
  chatMessages.value = []
  currentMessage.value = ''
  uploadChatMessage.value = ''
  isAITyping.value = false
  isProcessingOperation.value = false
  lastOperationType.value = ''
  clearError()

  // 🔥 创建新会话
  await createSession()
}

const exportResults = () => {
  if (convertedSheets.value.length > 0) {
    exportData()
  }
}

const refreshSourceData = () => {
  // 刷新原始数据显示
  activeSourceSheet.value = 0
}

const refreshConvertedData = () => {
  // 刷新转换后数据显示
  activeConvertedSheet.value = 0
}

// 🔥 新增：应用启动时初始化
onMounted(async () => {
  console.log('🚀 Excel转换系统正在初始化...')
  const success = await createSession()
  if (success) {
    console.log('✅ 系统初始化完成')
  } else {
    console.error('❌ 系统初始化失败')
  }
})

// 监听工作表切换，重置分页
watch(activeSourceSheet, () => {
  sourceCurrentPage.value = 1
  sourceJumpPage.value = 1
})

watch(activeConvertedSheet, () => {
  convertedCurrentPage.value = 1
  convertedJumpPage.value = 1
})
</script>

<style scoped>
.excel-converter {
  font-family: 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
  background: #f8fafc;
  color: #1f2937;
  line-height: 1.6;
  min-height: 100vh;
  background-image:
    radial-gradient(circle at 10% 20%, rgba(59, 130, 246, 0.02) 0%, transparent 20%),
    radial-gradient(circle at 90% 80%, rgba(6, 182, 212, 0.02) 0%, transparent 20%);
  background-size: 80px 80px;
}

.container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 2rem;
}

/* 标题样式 */
.header {
  text-align: center;
  margin-bottom: 3rem;
}

.main-title {
  font-size: 2.5rem;
  font-weight: 700;
  line-height: 1.2;
  background: linear-gradient(135deg, #3b82f6, #06b6d4);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  margin-bottom: 0.5rem;
}

.subtitle {
  font-size: 1.25rem;
  color: #6b7280;
  font-weight: 500;
}

/* 🔥 新增：会话状态指示器样式 */
.session-status {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  margin-top: 1rem;
  padding: 0.5rem 1rem;
  border-radius: 1rem;
  font-size: 0.875rem;
  transition: all 0.3s;
}

.session-status.connecting {
  background: rgba(245, 158, 11, 0.1);
  color: #f59e0b;
}

.session-status.active {
  background: rgba(16, 185, 129, 0.1);
  color: #10b981;
}

.session-status.expired {
  background: rgba(239, 68, 68, 0.1);
  color: #ef4444;
}

.session-status.error {
  background: rgba(239, 68, 68, 0.1);
  color: #ef4444;
}

.status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  animation: pulse 2s infinite;
}

.session-status.connecting .status-dot {
  background: #f59e0b;
}

.session-status.active .status-dot {
  background: #10b981;
}

.session-status.expired .status-dot,
.session-status.error .status-dot {
  background: #ef4444;
}

.status-text {
  font-weight: 500;
}

.session-id {
  font-family: monospace;
  font-size: 0.75rem;
  opacity: 0.7;
}

@keyframes pulse {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.5;
  }
}

/* 上传区域布局 */
.upload-container {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2rem;
  margin-bottom: 3rem;
}

/* 上传卡片样式 */
.upload-card {
  background: rgba(255, 255, 255, 0.7);
  border-radius: 1rem;
  padding: 2rem;
  box-shadow: 0 4px 20px rgba(59, 130, 246, 0.08);
  border: 1px solid rgba(59, 130, 246, 0.1);
  backdrop-filter: blur(10px);
  text-align: center;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.upload-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 30px rgba(59, 130, 246, 0.15);
}

.upload-card h3 {
  font-size: 1.5rem;
  font-weight: 600;
  margin-bottom: 1rem;
  color: #1f2937;
}

.upload-icon {
  font-size: 3rem;
  margin-bottom: 1rem;
}

.upload-area {
  border: 2px dashed rgba(59, 130, 246, 0.3);
  border-radius: 0.75rem;
  padding: 2rem;
  margin: 1.5rem 0;
  transition: all 0.3s;
  cursor: pointer;
}

.upload-area:hover {
  border-color: #3b82f6;
  background: rgba(59, 130, 246, 0.03);
}

.upload-text {
  font-size: 1.125rem;
  margin-bottom: 1rem;
  color: #64748b;
}

.browse-button {
  background: linear-gradient(135deg, #3b82f6, #2563eb);
  color: white;
  border: none;
  padding: 0.875rem 2rem;
  border-radius: 0.75rem;
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  min-width: 160px;
}

.browse-button:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 30px rgba(59, 130, 246, 0.15);
}

.file-info {
  margin-top: 1rem;
  padding: 1rem;
  background: rgba(59, 130, 246, 0.05);
  border-radius: 0.5rem;
}

.file-name {
  font-weight: 600;
  color: #3b82f6;
}

.file-size {
  color: #64748b;
  font-size: 0.875rem;
}

/* 🔥 新增：上传后的聊天区域样式 */
.upload-chat {
  margin-top: 2rem;
  margin-bottom: 2rem;
}

.upload-chat .chat-subtitle {
  color: #10b981;
  font-weight: 600;
}

.operation-hints {
  margin-bottom: 1.5rem;
  padding: 1rem;
  background: linear-gradient(135deg, rgba(59, 130, 246, 0.02), rgba(16, 185, 129, 0.02));
  border-radius: 0.75rem;
  border: 1px dashed rgba(59, 130, 246, 0.2);
}

.hint-title {
  font-size: 0.875rem;
  font-weight: 600;
  color: #1f2937;
  margin-bottom: 0.75rem;
}

.hint-examples {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.hint-item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem 1rem;
  background: rgba(255, 255, 255, 0.6);
  border: 1px solid rgba(59, 130, 246, 0.1);
  border-radius: 0.5rem;
  cursor: pointer;
  transition: all 0.3s;
  font-size: 0.875rem;
}

.hint-item:hover {
  background: rgba(59, 130, 246, 0.05);
  border-color: #3b82f6;
  transform: translateX(4px);
}

.hint-icon {
  font-size: 1.2rem;
}

/* 转换按钮区域 */
.convert-section {
  text-align: center;
  margin: 2rem 0;
}

.convert-button {
  background: linear-gradient(135deg, #3b82f6, #06b6d4);
  color: white;
  border: none;
  padding: 1rem 2.5rem;
  border-radius: 0.75rem;
  font-size: 1.125rem;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  box-shadow: 0 4px 15px rgba(59, 130, 246, 0.2);
}

.convert-button:hover:not(:disabled) {
  transform: translateY(-2px);
  box-shadow: 0 8px 25px rgba(59, 130, 246, 0.3);
}

.convert-button:disabled {
  background: #94a3b8;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

/* 错误消息样式 */
.error-message {
  position: fixed;
  top: 2rem;
  right: 2rem;
  z-index: 1000;
  animation: slideIn 0.3s ease-out;
}

.error-content {
  background: rgba(239, 68, 68, 0.95);
  color: white;
  padding: 1rem 1.5rem;
  border-radius: 0.5rem;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  box-shadow: 0 4px 20px rgba(239, 68, 68, 0.3);
  backdrop-filter: blur(10px);
  max-width: 400px;
}

.error-icon {
  font-size: 1.2rem;
}

.error-close {
  background: none;
  border: none;
  color: white;
  font-size: 1.5rem;
  cursor: pointer;
  padding: 0;
  margin-left: auto;
}

@keyframes slideIn {
  from {
    transform: translateX(100%);
    opacity: 0;
  }
  to {
    transform: translateX(0);
    opacity: 1;
  }
}

/* 结果页面 */
.results-section {
  animation: fadeIn 0.5s ease-in-out;
}

.back-section {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 2rem;
}

.back-button {
  background: rgba(255, 255, 255, 0.8);
  border: 1px solid rgba(59, 130, 246, 0.2);
  border-radius: 0.5rem;
  padding: 0.75rem 1.5rem;
  font-size: 1rem;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s;
  color: #3b82f6;
}

.back-button:hover {
  background: rgba(59, 130, 246, 0.05);
  border-color: #3b82f6;
  transform: translateX(-2px);
}

.export-button {
  background: linear-gradient(135deg, #10b981, #059669);
  color: white;
  border: none;
  border-radius: 0.5rem;
  padding: 0.75rem 1.5rem;
  font-size: 1rem;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s;
}

.export-button:hover:not(:disabled) {
  transform: translateY(-2px);
  box-shadow: 0 4px 15px rgba(16, 185, 129, 0.3);
}

.export-button:disabled {
  background: #94a3b8;
  cursor: not-allowed;
}

/* 全局操作区域 */
.global-actions {
  display: flex;
  gap: 0.75rem;
  align-items: center;
}

.action-btn {
  background: rgba(255, 255, 255, 0.8);
  border: 1px solid rgba(59, 130, 246, 0.2);
  border-radius: 0.5rem;
  padding: 0.75rem 1rem;
  font-size: 0.875rem;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s;
  color: #64748b;
}

.action-btn:hover {
  background: rgba(59, 130, 246, 0.05);
  border-color: #3b82f6;
  color: #3b82f6;
}

/* 表格显示区域 */
.tables-container {
  display: grid;
  grid-template-rows: auto 1fr;
  gap: 2rem;
  margin-bottom: 2rem;
}

.table-section {
  background: rgba(255, 255, 255, 0.7);
  border-radius: 1rem;
  padding: 2rem;
  box-shadow: 0 4px 20px rgba(59, 130, 246, 0.08);
  border: 1px solid rgba(59, 130, 246, 0.1);
  backdrop-filter: blur(10px);
}

.table-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 1.5rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid rgba(59, 130, 246, 0.1);
}

/* 表格标题区域改进 */
.table-title-section {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.table-title {
  font-size: 1.5rem;
  font-weight: 600;
  color: #1f2937;
  margin: 0;
}

.table-info {
  display: flex;
  gap: 1rem;
  font-size: 0.875rem;
  color: #64748b;
}

.sheet-count,
.row-count {
  background: rgba(59, 130, 246, 0.1);
  padding: 0.25rem 0.75rem;
  border-radius: 1rem;
  font-weight: 500;
  color: #3b82f6;
}

.table-actions {
  display: flex;
  gap: 0.75rem;
}

/* 折叠按钮样式 */
.collapse-button {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  background: rgba(255, 255, 255, 0.8);
  border: 1px solid rgba(59, 130, 246, 0.2);
  border-radius: 0.5rem;
  padding: 0.5rem 1rem;
  font-size: 0.875rem;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s;
  color: #64748b;
}

.collapse-button.active {
  background: rgba(59, 130, 246, 0.1);
  border-color: #3b82f6;
  color: #3b82f6;
}

.collapse-button:hover {
  background: rgba(59, 130, 246, 0.05);
  border-color: #3b82f6;
  color: #3b82f6;
  transform: translateY(-1px);
}

.collapse-icon {
  transition: transform 0.3s ease;
  font-size: 0.75rem;
}

.action-button {
  background: rgba(255, 255, 255, 0.8);
  border: 1px solid rgba(59, 130, 246, 0.2);
  border-radius: 0.5rem;
  padding: 0.5rem 1rem;
  font-size: 0.875rem;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s;
}

.action-button:hover {
  background: rgba(59, 130, 246, 0.05);
  border-color: #3b82f6;
}

.table-tabs {
  display: flex;
  gap: 0.5rem;
  margin-bottom: 1.5rem;
  overflow-x: auto;
}

.table-tab {
  display: flex;
  align-items: center;
  padding: 0.5rem 1rem;
  background: rgba(255, 255, 255, 0.5);
  border: 1px solid rgba(59, 130, 246, 0.2);
  border-radius: 0.5rem;
  font-size: 0.875rem;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s;
  white-space: nowrap;
}

.table-tab.active {
  background: rgba(59, 130, 246, 0.1);
  border-color: #3b82f6;
  color: #3b82f6;
}

/* 标签页行数显示 */
.tab-row-count {
  font-size: 0.75rem;
  color: #94a3b8;
  margin-left: 0.5rem;
}

/* 表格样式 - 重点优化部分 */
.table-wrapper {
  overflow-x: auto;
  border-radius: 0.5rem;
  border: 1px solid rgba(59, 130, 246, 0.1);
  max-width: 100%;
}

.data-table {
  width: 100%;
  border-collapse: collapse;
  min-width: 600px;
  table-layout: fixed; /* 固定表格布局，确保列宽控制生效 */
}

/* 表格单元格基础样式 */
.table-cell {
  padding: 0;
  border-bottom: 1px solid rgba(59, 130, 246, 0.05);
  position: relative;
  width: auto;
  min-width: 120px; /* 设置最小宽度 */
  max-width: 200px; /* 设置最大宽度 */
}

/* 单元格内容容器 */
.cell-content {
  padding: 1rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  display: block;
  width: 100%;
  box-sizing: border-box;
}

/* 表头样式 */
.data-table th.table-cell {
  background: rgba(59, 130, 246, 0.05);
  font-weight: 600;
  color: #1f2937;
  border-bottom: 1px solid rgba(59, 130, 246, 0.1);
}

.data-table th .cell-content {
  font-weight: 600;
  color: #1f2937;
}

/* 表体行样式 */
.data-table tbody tr {
  transition: all 0.2s ease;
}

.data-table tbody tr:nth-child(even) {
  background-color: rgba(59, 130, 246, 0.01);
}

.data-table tbody tr:hover {
  background: rgba(59, 130, 246, 0.03);
  transform: translateY(-1px);
  box-shadow: 0 2px 4px rgba(59, 130, 246, 0.1);
}

/* 悬停效果增强 */
.table-cell:hover {
  background: rgba(59, 130, 246, 0.05);
  cursor: default;
  z-index: 10;
}

.table-cell:hover .cell-content {
  color: #1f2937;
}

/* 长内容提示样式 */
.table-cell[title]:hover::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(59, 130, 246, 0.02);
  border: 1px solid rgba(59, 130, 246, 0.1);
  border-radius: 0.25rem;
  pointer-events: none;
  z-index: 1;
}

/* 针对不同列宽度的响应式调整 */
.data-table th:first-child,
.data-table td:first-child {
  min-width: 100px;
  max-width: 150px;
}

.data-table th:nth-child(2),
.data-table td:nth-child(2) {
  min-width: 120px;
  max-width: 180px;
}

.data-table th:nth-child(n + 3),
.data-table td:nth-child(n + 3) {
  min-width: 100px;
  max-width: 200px;
}

/* 特殊情况：超长文本的处理 */
.cell-content.long-text {
  max-width: 150px;
}

/* 数字类型单元格右对齐 */
.cell-content.number {
  text-align: right;
}

/* 分页组件样式 */
.pagination-container {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1.5rem 1rem;
  margin-top: 1rem;
  background: rgba(59, 130, 246, 0.02);
  border-radius: 0.75rem;
  border: 1px solid rgba(59, 130, 246, 0.1);
  flex-wrap: wrap;
  gap: 1rem;
}

.pagination-info {
  display: flex;
  align-items: center;
  gap: 1rem;
  font-size: 0.875rem;
  color: #64748b;
}

.total-info {
  font-weight: 500;
}

.page-size-selector {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.page-size-select {
  padding: 0.25rem 0.5rem;
  border: 1px solid rgba(59, 130, 246, 0.2);
  border-radius: 0.375rem;
  background: rgba(255, 255, 255, 0.8);
  font-size: 0.875rem;
  cursor: pointer;
  transition: all 0.3s;
}

.page-size-select:focus {
  outline: none;
  border-color: #3b82f6;
  box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);
}

.pagination-controls {
  display: flex;
  align-items: center;
  gap: 0.25rem;
}

.pagination-btn {
  padding: 0.5rem 0.875rem;
  border: 1px solid rgba(59, 130, 246, 0.2);
  background: rgba(255, 255, 255, 0.8);
  color: #64748b;
  border-radius: 0.375rem;
  font-size: 0.875rem;
  cursor: pointer;
  transition: all 0.3s;
  min-width: 44px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.pagination-btn:hover:not(:disabled) {
  background: rgba(59, 130, 246, 0.05);
  border-color: #3b82f6;
  color: #3b82f6;
  transform: translateY(-1px);
}

.pagination-btn:disabled {
  background: rgba(107, 114, 128, 0.05);
  color: #9ca3af;
  cursor: not-allowed;
  border-color: rgba(107, 114, 128, 0.2);
}

.pagination-pages {
  display: flex;
  gap: 0.25rem;
  margin: 0 0.5rem;
}

.page-btn.active {
  background: linear-gradient(135deg, #3b82f6, #2563eb);
  color: white;
  border-color: #3b82f6;
}

.page-btn.active:hover {
  transform: translateY(-1px);
  box-shadow: 0 2px 8px rgba(59, 130, 246, 0.3);
}

.pagination-jump {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.875rem;
  color: #64748b;
}

.page-jump-input {
  width: 60px;
  padding: 0.25rem 0.5rem;
  border: 1px solid rgba(59, 130, 246, 0.2);
  border-radius: 0.375rem;
  background: rgba(255, 255, 255, 0.8);
  font-size: 0.875rem;
  text-align: center;
  transition: all 0.3s;
}

.page-jump-input:focus {
  outline: none;
  border-color: #3b82f6;
  box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);
}

.jump-btn {
  padding: 0.25rem 0.75rem;
  border: 1px solid rgba(59, 130, 246, 0.2);
  background: rgba(255, 255, 255, 0.8);
  color: #3b82f6;
  border-radius: 0.375rem;
  font-size: 0.875rem;
  cursor: pointer;
  transition: all 0.3s;
}

.jump-btn:hover {
  background: rgba(59, 130, 246, 0.05);
  border-color: #3b82f6;
  transform: translateY(-1px);
}

/* 表格折叠动画 */
.table-collapse-enter-active,
.table-collapse-leave-active {
  transition: all 0.3s ease;
  overflow: hidden;
}

.table-collapse-enter-from,
.table-collapse-leave-to {
  opacity: 0;
  max-height: 0;
  transform: translateY(-10px);
}

.table-collapse-enter-to,
.table-collapse-leave-from {
  opacity: 1;
  max-height: 1000px;
  transform: translateY(0);
}

/* 表格摘要卡片 */
.table-summary {
  margin-top: 1rem;
  padding: 0;
}

.summary-card {
  display: flex;
  align-items: center;
  gap: 1rem;
  background: rgba(59, 130, 246, 0.02);
  border: 1px dashed rgba(59, 130, 246, 0.2);
  border-radius: 0.75rem;
  padding: 1.5rem;
  transition: all 0.3s ease;
}

.summary-card:hover {
  background: rgba(59, 130, 246, 0.03);
  border-color: rgba(59, 130, 246, 0.3);
}

.summary-icon {
  font-size: 2rem;
  opacity: 0.6;
}

.summary-content {
  flex: 1;
}

.summary-title {
  font-size: 1rem;
  font-weight: 600;
  color: #1f2937;
  margin-bottom: 0.25rem;
}

.summary-details {
  font-size: 0.875rem;
  color: #64748b;
  line-height: 1.4;
}

/* 空状态 */
.empty-state {
  text-align: center;
  padding: 3rem;
  color: #64748b;
}

.empty-icon {
  font-size: 3rem;
  margin-bottom: 1rem;
  opacity: 0.5;
}

/* 状态指示器 */
.status-indicator {
  display: inline-flex;
  align-items: center;
  padding: 0.25rem 0.75rem;
  border-radius: 1rem;
  font-size: 0.875rem;
  font-weight: 500;
  margin-top: 1rem;
}

.status-waiting {
  background: rgba(107, 114, 128, 0.1);
  color: #6b7280;
}

.status-ready {
  background: rgba(16, 185, 129, 0.1);
  color: #10b981;
}

.status-processing {
  background: rgba(245, 158, 11, 0.1);
  color: #f59e0b;
}

/* AI助手对话框样式 */
.chat-container {
  background: rgba(255, 255, 255, 0.7);
  border-radius: 1rem;
  margin-top: 2rem;
  box-shadow: 0 4px 20px rgba(59, 130, 246, 0.08);
  border: 1px solid rgba(59, 130, 246, 0.1);
  backdrop-filter: blur(10px);
  overflow: hidden;
}

.chat-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1.5rem 2rem;
  background: linear-gradient(135deg, rgba(59, 130, 246, 0.05), rgba(6, 182, 212, 0.05));
  border-bottom: 1px solid rgba(59, 130, 246, 0.1);
}

.chat-title-section {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.chat-icon {
  font-size: 2rem;
  background: linear-gradient(135deg, #3b82f6, #06b6d4);
  border-radius: 50%;
  width: 50px;
  height: 50px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.chat-title {
  font-size: 1.25rem;
  font-weight: 600;
  color: #1f2937;
  margin: 0;
}

.chat-subtitle {
  font-size: 0.875rem;
  color: #64748b;
  margin: 0;
  margin-top: 0.25rem;
}

.chat-toggle {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  background: rgba(255, 255, 255, 0.8);
  border: 1px solid rgba(59, 130, 246, 0.2);
  border-radius: 0.5rem;
  padding: 0.5rem 1rem;
  font-size: 0.875rem;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s;
  color: #64748b;
}

.chat-toggle.active {
  background: rgba(59, 130, 246, 0.1);
  border-color: #3b82f6;
  color: #3b82f6;
}

.chat-toggle:hover {
  background: rgba(59, 130, 246, 0.05);
  border-color: #3b82f6;
  color: #3b82f6;
}

.toggle-icon {
  transition: transform 0.3s ease;
  font-size: 0.75rem;
}

.chat-content {
  padding: 1.5rem;
}

/* 对话框折叠动画 */
.chat-collapse-enter-active,
.chat-collapse-leave-active {
  transition: all 0.3s ease;
  overflow: hidden;
}

.chat-collapse-enter-from,
.chat-collapse-leave-to {
  opacity: 0;
  max-height: 0;
  transform: translateY(-10px);
}

.chat-collapse-enter-to,
.chat-collapse-leave-from {
  opacity: 1;
  max-height: 600px;
  transform: translateY(0);
}

/* 消息列表 */
.chat-messages {
  max-height: 400px;
  overflow-y: auto;
  padding: 1rem 0;
  margin-bottom: 1rem;
}

.message {
  display: flex;
  gap: 0.75rem;
  margin-bottom: 1rem;
  animation: messageSlideIn 0.3s ease-out;
}

.message.user {
  flex-direction: row-reverse;
}

.message-avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1rem;
  flex-shrink: 0;
}

.message.user .message-avatar {
  background: linear-gradient(135deg, #3b82f6, #2563eb);
}

.message.assistant .message-avatar {
  background: linear-gradient(135deg, #10b981, #059669);
}

.message-content {
  flex: 1;
  max-width: 80%;
}

.message.user .message-content {
  text-align: right;
}

.message-text {
  background: rgba(59, 130, 246, 0.05);
  padding: 0.75rem 1rem;
  border-radius: 1rem;
  font-size: 0.875rem;
  line-height: 1.5;
  word-wrap: break-word;
}

.message.user .message-text {
  background: linear-gradient(135deg, #3b82f6, #2563eb);
  color: white;
  border-bottom-right-radius: 0.25rem;
}

.message.assistant .message-text {
  background: rgba(16, 185, 129, 0.05);
  border: 1px solid rgba(16, 185, 129, 0.1);
  border-bottom-left-radius: 0.25rem;
}

/* 🔥 新增：消息文本中的样式 */
.message-text :deep(strong) {
  font-weight: 700;
  color: #1f2937;
}

.message-text :deep(em) {
  font-style: italic;
  color: #4b5563;
}

.message-text :deep(.emoji) {
  font-size: 1.1rem;
  margin: 0 0.1rem;
}

.message-time {
  font-size: 0.75rem;
  color: #94a3b8;
  margin-top: 0.25rem;
}

/* 正在输入动画 */
.typing-indicator {
  display: flex;
  gap: 0.25rem;
  padding: 0.75rem 1rem;
}

.typing-indicator span {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #94a3b8;
  animation: typingBounce 1.4s infinite ease-in-out both;
}

.typing-indicator span:nth-child(1) {
  animation-delay: -0.32s;
}
.typing-indicator span:nth-child(2) {
  animation-delay: -0.16s;
}
.typing-indicator span:nth-child(3) {
  animation-delay: 0s;
}

@keyframes typingBounce {
  0%,
  80%,
  100% {
    transform: scale(0);
  }
  40% {
    transform: scale(1);
  }
}

/* 快捷问题 */
.quick-questions {
  margin-bottom: 1rem;
  padding: 1rem;
  background: rgba(59, 130, 246, 0.02);
  border-radius: 0.75rem;
  border: 1px dashed rgba(59, 130, 246, 0.2);
}

.quick-title {
  font-size: 0.875rem;
  font-weight: 600;
  color: #1f2937;
  margin-bottom: 0.75rem;
}

.quick-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.quick-button {
  background: rgba(255, 255, 255, 0.8);
  border: 1px solid rgba(59, 130, 246, 0.2);
  border-radius: 1rem;
  padding: 0.5rem 1rem;
  font-size: 0.75rem;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s;
  color: #3b82f6;
}

.quick-button:hover {
  background: rgba(59, 130, 246, 0.1);
  border-color: #3b82f6;
  transform: translateY(-1px);
}

/* 输入区域 */
.chat-input-area {
  border-top: 1px solid rgba(59, 130, 246, 0.1);
  padding-top: 1rem;
}

.input-wrapper {
  display: flex;
  gap: 0.75rem;
  align-items: flex-end;
}

.chat-input {
  flex: 1;
  border: 1px solid rgba(59, 130, 246, 0.2);
  border-radius: 0.75rem;
  padding: 0.75rem 1rem;
  font-size: 0.875rem;
  line-height: 1.5;
  resize: none;
  transition: all 0.3s;
  background: rgba(255, 255, 255, 0.8);
  min-height: 40px;
  max-height: 120px;
}

.chat-input:focus {
  outline: none;
  border-color: #3b82f6;
  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}

.chat-input:disabled {
  background: rgba(107, 114, 128, 0.05);
  color: #9ca3af;
  cursor: not-allowed;
}

.send-button {
  background: linear-gradient(135deg, #3b82f6, #2563eb);
  color: white;
  border: none;
  border-radius: 0.75rem;
  padding: 0.75rem 1.5rem;
  font-size: 0.875rem;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s;
  height: 40px;
  min-width: 100px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.send-button:hover:not(:disabled) {
  transform: translateY(-2px);
  box-shadow: 0 4px 15px rgba(59, 130, 246, 0.3);
}

.send-button:disabled {
  background: #94a3b8;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

.input-hint {
  font-size: 0.75rem;
  color: #94a3b8;
  margin-top: 0.5rem;
  text-align: center;
}

/* 加载动画 */
.loading-spinner {
  display: inline-block;
  width: 1rem;
  height: 1rem;
  border: 2px solid rgba(59, 130, 246, 0.3);
  border-radius: 50%;
  border-top-color: #3b82f6;
  animation: spin 1s ease-in-out infinite;
  margin-right: 0.5rem;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes messageSlideIn {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* 响应式设计 */
@media (max-width: 1024px) {
  .upload-container {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 768px) {
  .container {
    padding: 1rem;
  }

  .main-title {
    font-size: 2rem;
  }

  .upload-card {
    padding: 1.5rem;
  }

  .table-section {
    padding: 1.5rem;
  }

  .table-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 1rem;
  }

  .table-actions {
    width: 100%;
    justify-content: flex-end;
  }

  .back-section {
    flex-direction: column;
    gap: 1rem;
    align-items: stretch;
  }

  .global-actions {
    flex-direction: column;
    width: 100%;
  }

  .table-title-section {
    align-items: flex-start;
  }

  .table-info {
    flex-direction: column;
    gap: 0.5rem;
  }

  .table-actions {
    flex-direction: column;
    gap: 0.5rem;
    width: 100%;
  }

  .collapse-button,
  .action-button {
    width: 100%;
    justify-content: center;
  }

  .summary-card {
    flex-direction: column;
    text-align: center;
    gap: 0.75rem;
  }

  .summary-content {
    text-align: center;
  }

  .error-message {
    top: 1rem;
    right: 1rem;
    left: 1rem;
  }

  .error-content {
    max-width: none;
  }

  /* 对话框响应式 */
  .chat-header {
    padding: 1rem;
    flex-direction: column;
    gap: 1rem;
    align-items: flex-start;
  }

  .chat-content {
    padding: 1rem;
  }

  .chat-messages {
    max-height: 300px;
  }

  .message-content {
    max-width: 90%;
  }

  .input-wrapper {
    flex-direction: column;
    align-items: stretch;
  }

  .send-button {
    width: 100%;
  }

  .quick-buttons {
    flex-direction: column;
  }

  .quick-button {
    text-align: center;
  }

  /* 🔥 操作提示响应式 */
  .hint-examples {
    gap: 0.375rem;
  }

  .hint-item {
    padding: 0.5rem 0.75rem;
    font-size: 0.8rem;
  }

  .hint-icon {
    font-size: 1rem;
  }

  /* 表格响应式调整 */
  .data-table {
    min-width: 100%;
    table-layout: auto;
  }

  .table-cell {
    min-width: 80px;
    max-width: 120px;
  }

  .cell-content {
    padding: 0.75rem 0.5rem;
    font-size: 0.875rem;
  }

  .data-table th:first-child,
  .data-table td:first-child {
    min-width: 80px;
    max-width: 100px;
  }

  .data-table th:nth-child(2),
  .data-table td:nth-child(2) {
    min-width: 90px;
    max-width: 120px;
  }

  .data-table th:nth-child(n + 3),
  .data-table td:nth-child(n + 3) {
    min-width: 80px;
    max-width: 150px;
  }

  /* 分页组件响应式设计 */
  .pagination-container {
    flex-direction: column;
    align-items: stretch;
    gap: 1rem;
  }

  .pagination-info {
    justify-content: space-between;
  }

  .pagination-controls {
    justify-content: center;
    flex-wrap: wrap;
    gap: 0.25rem;
  }

  .pagination-pages {
    margin: 0;
  }

  .pagination-btn {
    padding: 0.375rem 0.625rem;
    font-size: 0.8rem;
    min-width: 36px;
    height: 32px;
  }

  .pagination-jump {
    justify-content: center;
  }

  /* 🔥 会话状态响应式 */
  .session-status {
    flex-direction: column;
    gap: 0.25rem;
    text-align: center;
    padding: 0.75rem 1rem;
  }

  .session-id {
    font-size: 0.7rem;
  }
}

@media (max-width: 480px) {
  .table-cell {
    min-width: 60px;
    max-width: 100px;
  }

  .cell-content {
    padding: 0.5rem 0.25rem;
    font-size: 0.8rem;
  }

  .pagination-container {
    padding: 1rem 0.5rem;
  }

  .pagination-info {
    flex-direction: column;
    gap: 0.5rem;
    align-items: stretch;
  }

  .page-size-selector {
    justify-content: space-between;
  }

  .pagination-controls {
    gap: 0.125rem;
  }

  .pagination-btn {
    padding: 0.25rem 0.5rem;
    font-size: 0.75rem;
    min-width: 32px;
    height: 28px;
  }

  .page-jump-input {
    width: 50px;
  }
}

/* 滚动条样式 */
.excel-converter ::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

.excel-converter ::-webkit-scrollbar-track {
  background: rgba(59, 130, 246, 0.05);
  border-radius: 3px;
}

.excel-converter ::-webkit-scrollbar-thumb {
  background: rgba(59, 130, 246, 0.2);
  border-radius: 3px;
}

.excel-converter ::-webkit-scrollbar-thumb:hover {
  background: rgba(59, 130, 246, 0.3);
}
</style>
